home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
ShareWare OnLine 2
/
ShareWare OnLine Volume 2 (CMS Software)(1993).iso
/
util2
/
stpprg20.zip
/
STOPPRG.ASM
next >
Wrap
Assembly Source File
|
1993-03-05
|
34KB
|
853 lines
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; StopPrg, by MAK-TRAXON's Prophet ;;
;; Started October 1992 ;;
;; Version 2.0 : latest update: 27/2/1993 ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
progseg segment public
assume cs:progseg,ss:progseg,es:progseg,ds:progseg
page 60,80
org 100h
; MASM-compatible header for .COM file
wo equ word ptr
by equ byte ptr
dwo equ dword ptr
jmps equ jmp short
; some handy shortcuts
entpt: jmp install ; jump to init routines
;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ABOUT STOPPRG ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; StopPrg was started about October 1992 by MAK-TRAXON's Prophet at the
; Club Info of the Lycee Louis-le-Grand. Its 1st version recognized the hot
; key LeftShift - RightShift to either exit to DOS or hang the computer.
; Saving a copy of the interrupt table and avoiding to interrupt an int 9
; helped to make StopPrg exit to DOS more often than hang the computer.
; It was also made possible to choose the hot key among combinations of Shifts
; Ctrl and Alt. This worked OK except with games and uncivilised programs which
; take int 9 witout chaining it; they would simply ignore StopPrg.
;
; This new version has been specifically designed to insist taking int 9 up
; to 10 times, even in the middle of the execution of a program, so that it
; can always have control over int 9. The hot key has been changed to Alt -
; Ctrl - Enter, and can no longer be changed except by recompiling, and the
; /M (maximum compatibility) command line option has been added. With this
; option, int 9 will not be taken more than once.
;
; How does StopPrg work? The idea is simple: it takes int 9, reads the keyboard
; and when Alt - Ctrl - Enter is pressed, issues an Int 21h with ah = 4ch.
; To have this work reliably, it must also take a number of precautions: every
; time a program is executed, StopPrg saves a copy of the entire interrupt
; table, to restore it when it activates. This allows to exit from programs
; which take interrupts during their execution, and restore them afterwards.
; StopPrg also avoids activating during a disk access (that is during an
; int 13h), and less than 3 seconds after the last activation. To be able to
; take int 9 more than once, it must have a number of int 9 entry points or
; slots (10 in this version), and a way to free them when the program which
; used a slot has restored its interrupt; this is done when a program exits
; to DOS using int 20h, int 27h or int 21h functions 0, 4ch or 31h.
;
; There are some particular conditions where StopPrg is not so reliable:
; when the EXEC function (4b00h) has been used in chain by several programs
; (DOS shelling from applications), StopPrg can only reliably be used once
; to exit from the "topmost" program. This happens because when the topmost
; program was loaded StopPrg saved the interrupt table, so when it exits
; it can no longer restore the interrupt table corresponding to before the
; next program was loaded. This is of course no problem if these programs did
; not alter the interrupt table.
;
; Also activating StopPrg from a Pop-Up resident is not reliable and cannot be
; recommended; if the Pop-Up did not activate its PSP this will probably exit
; the current application as well as the Pop-Up, possibly leaving the Pop-Up
; in an unstable state. If it did, and no other program has been executed
; in between, then StopPrg should restore the interrupt table, effectively
; disabling the Pop-Up, and the DOS Exit function executed with the Pop-Up's
; PSP active should even free its memory! (I tried this with my Resident Norton
; Editor, and it worked!)
; Also activating StopPrg from the DOS prompt will restore the interrupt table,
; and this will disable the last program if it was a TSR, without freeing its
; memory. If it was not a TSR, then StopPrg will do little more than Cls
; (this is safe but typing Cls is still safer !).
;
; An unwanted effect of StopPrg's taking int 9 more than once is that if a TSR
; is loaded after StopPrg, and it takes int 9 (most TSRs do), then int 9 will
; appear to have been taken again, so the resident will refuse to uninstall
; (or only disable itself without freeing its memory or restoring its
; interrupt vectors). To correct this, StopPrg will attempt to catch the
; uninstalling program reading the interrupt table and, if StopPrg has taken
; int 9 more than once, it will give the last int 9 vector instead of its own
; slot address. This works as long as the uninstalling program uses DOS
; function 35h to read an interrupt vector, instead of reading directly at
; 0000:00024h. This should also make that, when a TSR is installed after
; StopPrg, StopPrg will only once check if its hot-key has been pressed
; instead of doing it as many times as it has taken int 9 (this makes no
; practial difference, and applies only if the TSR uses the DOS to read the
; interrupt table).
;
; Finally, a word about SideKick compatibility: SideKick versions 1.x has
; a bug in it. It takes int 9, and if int 9 is taken by some other program,
; it will take it again at the next clock tick, making it point to a secondary
; handler which only checks the shift state and stores it in a variable. Now
; if a resident program, when SideKick has already done this, takes int 9 again
; (this can happen if a game using int 9 is loaded after a resident which uses
; it too), SideKick will take it again (3rd time!) and make it point to the
; SAME handler. So the second return address will be lost, and int 9 will
; recurse, hopelessly hanging the computer (try it!). Since StopPrg uses a
; similar technique to take int 9 up to 10 times, it would be sure to be
; incompatible with SideKick. The solution: find SideKick in memory, and poke
; a byte to disable taking int 9 more than once. This works (i.e the computer
; does not hang and both StopPrg and SideKick respond to their keys) at least
; with SideKick version 1.56A, and should not change between versions 1.x,
; since no absolute addresses are used. In any case, if some resident prog
; does not seem to work with StopPrg, try loading StopPrg after the resident,
; and if it still does not work, use the /M option.
;;;;;;;;;;;;;;;;;;;;;;;;;;;; MORE ABOUT STOPPRG ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; StopPrg's internal programmer interface:
; * checking whether StopPrg is loaded: issue an Int 21h with AX = 3022h.
; DOS will give you AX = version number, and StopPrg will put
; CX = 1112h and BX = segment where StopPrg is loaded
; * telling StopPrg not to activate: put the value 9090h in 0:4feh
; (in the Inter-Application-Communication-Area) (Somebody had to use it
; one day!).
; Remember to restore the previous value (or set it to 0) on exit.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; CONSTANTS ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
nb_slots = 10 ; number of int 9 slots
;;;;;;;;;;;;;;;;;;;;;;;;;;;; RESIDENT DATA ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
old8 label dword ; saved int 8 vector
db 01ah,0,0,0 ; 4 bytes
old20 dd 0 ; saved int 20h vector
old27 dd 0 ; saved int 27h vector
old13 dd 0 ; saved int 13h vector
out9 dd 0 ; address where to jmp to give control from
; an int 9
old21 dd 0 ; saved int 21 vector
dosavail dd 0 ; address of InDos flag
in13 db 0 ; flag: is an int 13h in execution ?
jdone db 0 ; flag: has StopPrg just been activated ?
; Set to 36 by a StopPrg activation,
; decremented by Int 8, and StopPrg will not
; activate if it is not 0.
ints db 400h dup (0) ; copy of the interrupt table
; (restored at exit)
nomsg db 0 ; flag: were we asked not to print any messages
; unless something goes wrong ?
un_inst db 0 ; flag: were we asked to uninstall ?
soft db 0 ; flag: were we asked to use "very compatible"
; interrupt handlings ?
ctrl db 0 ; flag: set to 36 by int 9 when Ctrl is pressed
; decremented by int 8
alt db 0 ; same thing with Alt
slot db 0 ; which is the last int 9 slot that has been
; used ?
old9 label dword
slots dd nb_slots dup (0)
;;;;;;;;;;;;;;;;;;;;;;;;;;;; INTERRUPT HANDLERS ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; the different int 9 slots
new9 label near ; address of first slot
which_slot = 0
slot_0 label near
rept nb_slots ; assembler directive: assemble nb_slots times
local start_slot
start_slot: push ax
mov al,which_slot
jmps int_9
slot_len = $ - offset start_slot ; used later
which_slot = which_slot + 1
endm ; end of loop
; generic int 9 handler: AL = slot number (used for Exit), AX has been pushed
int_9: sti
push ax
in al,60h ; get scan code
cmp al,29 ; Ctrl
jnz noctrl
mov by cs:ctrl,36
jmps cont9
noctrl: cmp al,29+80h ; Ctrl released?
jnz noctrl2
mov by cs:ctrl,0
jmps cont9
noctrl2: cmp al,56 ; Alt
jnz noalt
mov by cs:alt,36
jmps cont9
noalt: cmp al,56+80h ; Alt released?
jnz noalt2
mov by cs:alt,0
jmps cont9
noalt2: cmp al,28 ; Cr
jnz cont9
cmp by cs:alt,0
jz cont9
cmp by cs:ctrl,0
jz cont9
cmp by cs:jdone,0
jnz cont9
cmp by cs:in13,0 ; activation if Cr was the key, Alt and Ctrl
jnz cont9 ; were already down, and jdone=in13=0
push ds
xor ax,ax
mov ds,ax
cmp wo ds:[4feh],9090h
pop ds
jnz hot_key
cont9: pop ax ; AL = slot number
push bx ; save BX
xor ah,ah
add ax,ax
add ax,ax
mov bx,ax
add bx,offset slots ; [BX] = address to jump
cli
mov ax,cs:[bx]
mov wo cs:out9,ax
inc bx
inc bx
mov ax,cs:[bx]
mov wo cs:out9[2],ax ; copy it to out9 (to free BX)
pop bx
pop ax ; pushed by each slot
jmp dwo cs:out9 ; give back control
hot_key: push cs ; if it was ...
pop ds ; ds = cs
mov by jdone,36 ; set the "activated" flag
les bx,dosavail
mov by es:[bx],0 ; set InDos to zero (tell the DOS it is
; not doing anything; if it was doing
; something it's lost anyway ...)
in al,61h
mov ah,al
or al,80h
out 61h,al
mov al,ah
out 61h,al ; tell the kbd controller that we're done
mov al,20h
out 20h,al ; same thing to the interrupt controller
cli ; disable interrupts
xor ax,ax
mov ds,ax ; ds = 0
push wo ds:[88h]
push wo ds:[8ah]
push wo ds:[8ch]
push wo ds:[8eh]
push wo ds:[90h] ; save int 22, 23, 24 vectors
push wo ds:[92h] ; (needed by DOS for Exit)
push ds
pop es
push cs
pop ds
mov si,offset ints
xor di,di
mov cx,200h
cld
rep movsw ; copy saved interrupt table to 0:0
xor ax,ax
mov ds,ax
pop wo ds:[92h]
pop wo ds:[90h]
pop wo ds:[8eh]
pop wo ds:[8ch]
pop wo ds:[8ah] ; recover int 22, 23 and 24 handlers
pop wo ds:[88h] ; (needed by DOS for Exit)
sti ; enable interrupts
in al,61h
and al,0feh
out 61h,al ; disable the speaker
mov al,36h
out 43h,al
mov al,0
out 40h,al ; set the standard int 8 rate
out 40h,al ; (many games change it)
mov al,by ds:[449h] ; get video mode
cmp al,7
jz contvmode
mov al,3
contvmode: xor ah,ah ; set it to 7 if it was 7, else set
int 10h ; it to 3
push cs
pop ds
push cs
pop es
mov ax,4c77h
int 21h ; exit to DOS
; Interrupt 8 (timer) handler
new8: cmp by cs:jdone,0 ; has StopPrg recently activated ?
jz nojdn
dec by cs:jdone ; if so, decrement flag ...
nojdn: cmp by cs:ctrl,0 ; was Ctrl recently pressed ?
jz noctr
dec by cs:ctrl ; if so dec flag ...
noctr: cmp by cs:alt,0 ; was Alt recently pressed ?
jz noal
dec by cs:alt ; if so dec flag ...
noal: cmp by cs:soft,0 ; do we have to be soft & compatible ?
jnz exit8 ; if so, exit
push es
push ax
push bx
push cx
mov al,8
call readint ; read int 8 vector
cmp wo es:[bx+1dh],0a1fah
jnz nosdk
cmp wo es:[bx+1fh],26h
jnz nosdk
cmp wo es:[bx+25h],74c3h
jnz nosdk ; is SideKick hooked on int 8 ?
mov by es:[bx+26h],0ebh
; if so, poke a byte in its code
; SideKick has a bug in it: if int 9 is stolen from it, it will take it again,
; making it point to a secondary int 9 handler. However, if this happens more
; than once, the resulting int 9 handler will recurse, hanging the system.
; since StopPrg will take int 9 up to 10 times, this would be sure to hang
; SideKick. We simply disable this (bugged) feature.
nosdk: mov al,9
call readint ; read int 9 vector
mov ax,es
mov cx,cs ; if segment = cs => exit (nothing to do)
cmp ax,cx
jz ok9
cmp by cs:slot,nb_slots-1
jnb ok9 ; if all the slots are taken, exit
push ds
push dx
push cs
pop ds
inc by slot
mov cx,bx ; ES:CX = int 9 to save
mov bl,slot
xor bh,bh
add bx,bx
add bx,bx ; CS:slots[BX] = where to save int 9 handler
mov wo slots[bx],cx
mov wo slots[bx][2],es
mov al,slot
mov ah,slot_len
mul ah
add ax,offset new9
mov dx,ax
mov al,9
call setint
pop dx
pop ds
ok9: pop cx
pop bx
pop ax
pop es
exit8: jmp dwo cs:old8 ; jmp to org int 8 handler
; Interrupt 21 (DOS) handler
new21: cmp ax,4b00h ; is function 4b00 ? (exec program)
jz func4b ; if so, handle it in func4b
cmp ah,0 ; is function 0 ... (exit to DOS)
jz exitDOS
cmp ah,4ch ; or function 4ch ... (exit with errorlevel)
jz exitDOS
cmp ah,31h ; or function 31h ? (TSR)
jnz noexitDOS
exitDOS: call recalc ; if so, recalculate slot
jmps exit21
noexitDOS: cmp ax,3022h ; is function 30h (get version), with
; special code 22h in AL ?
jnz noack ; if so,
pushf
call dwo cs:old21 ; call original int 21h handler
mov cx,1112h ; return acknowledgement code (1112h in CX)
mov bx,cs ; return program segment in BX
iret
noack: cmp ax,3509h ; is function 35h (read int vector) with AL=9 ?
jnz exit21 ; if not, exit
cmp cs:slot,0 ; if slot is 0 (the 1st one)
jz exit21
cmp cs:slot,nb_slots-1
jz exit21 ; or nb_slots-1 (the last one) then exit
mov bl,cs:slot
xor bh,bh
add bx,bx
add bx,bx
add bx,offset slots
les bx,cs:[bx] ; return (in ES:BX) the current slot's return
; address
iret
exit21: jmp dwo cs:old21 ; jump to original int 21h handler
func4b: call recalc ; recalculate slot number
push ax
push ds
push es
push si
push di
push cx ; save registers
xor ax,ax
mov ds,ax
push cs
pop es
xor si,si
mov di,offset ints
mov cx,200h
cld
rep movsw ; copy interrupt table to the "ints" buffer
pop cx
pop di
pop si
pop es
pop ds
pop ax ; restore saved registers
jmp exit21 ; jmp to original int 21h handler
new20: call recalc ; recalculate slot
jmp dwo cs:old20; jmp to original int 20h handler
new27: call recalc ; recalculate slot
jmp dwo cs:old27; jmp to original int 27h handler
new13: mov cs:in13,1 ; set flag
pushf
call dwo cs:old13 ; call original int 13h
mov cs:in13,0 ; reset flag
sti
retf 2 ; return preserving flags
;;;;;;;;;;;;;;;;;;;;;;;;;;;;; RESIDENT PROCEDURES ;;;;;;;;;;;;;;;;;;;;;;;;;;;
recalc proc
; recalculate slot : if int 9 is pointing to StopPrg, "slot" is the slot
; number to which it is pointing (free slots whose interrupts have been
; released by other programs)
cmp by cs:soft,0 ; are we soft ?
jnz exit_recalc ; if so, nothing to do (slot is always 0)
push ax
push bx
push cx
push es ; save registers
mov al,9
call readint ; read int 9 vector
mov cx,es
mov ax,cs
cmp ax,cx ; is it pointing to StopPrg ?
jnz end_recalc ; if not, exit
mov ax,bx
sub ax,offset new9 ; get offset of slot (int 9 entry point)
cmp ax,(nb_slots-1)*slot_len
; is it within the int 9 entry point table ?
ja end_recalc ; if not, exit
mov bl,slot_len
div bl ; calc slot number
mov cs:slot,al ; set slot number
end_recalc: pop es
pop cx
pop bx
pop ax ; restore regs
exit_recalc: ret
recalc endp
readint proc
; AL = int number => ES:BX = interrupt handler
xor bx,bx
mov es,bx
mov bl,al
add bx,bx
add bx,bx
les bx,es:[bx]
ret
readint endp
setint proc
; AL= int number, DS:DX = new int handler
push es
push bx
xor bx,bx
mov es,bx
mov bl,al
add bx,bx
add bx,bx
cli
mov es:[bx],dx
mov es:[bx+2],ds
sti
pop bx
pop es
ret
setint endp
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; INITIALISATION ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
install: mov si,81h ; address of command line tail
cld
loopchar: lodsb ; get a char
cmp al,' '
jz loopchar
cmp al,9
jz loopchar ; skip spaces and TABs
cmp al,'/'
jz loopchar ; skip slashes
cmp al,'-'
jz loopchar ; skip hyphens (alias for /)
and al,0dfh ; convert to uppercase
cmp al,'U' ; if it is U ...
jnz nou
inc un_inst ; set the UnInstall flag
jmps loopchar
nou: cmp al,'N' ; if it is N
jnz non
inc nomsg ; then put the NoMsg flag on
jmps loopchar
non: cmp al,'M' ; if it is M
jnz nom
inc soft ; then put the "soft" flag on
jmps loopchar
nom: cmp al,0dh ; if it is Cr
jz endcmd ; then we are done
; if we are here, some unrecognized letter was found
mov ah,9
mov dx,offset messprg
int 21h ; display prog name and info
mov ah,9
mov dx,offset messwrongcmd
int 21h ; complain
mov ax,4c01h
int 21h ; exit to DOS
endcmd: cmp nomsg,0
jnz no_msg1
mov ah,9
mov dx,offset messprg ; display prg name and info unless
int 21h ; asked not to do it
no_msg1: cmp un_inst,0
jnz uninstall
jmp nouninst ; jmp to nouninst if not asked to uninstall
; StopPrg has been asked to uninstall from memory
uninstall: mov ax,3022h
int 21h ; is it already there ?
cmp cx,1112h
jz noerr1
call progname ; disp. prog name even if asked not to do it
; (before complaining)
mov ah,9
mov dx,offset messerrnoinst
int 21h
mov ax,4c01h ; if not, complain and exit to DOS
int 21h
noerr1: mov bp,bx
mov es,bp ; ES = BP = segment of resident StopPrg
cmp es:slot,0 ; is the resident StopPrg in its first slot ?
jz noerr2
call progname ; if not so, disp. prog name even if asked not
; to do it
mov ah,9
mov dx,offset messerrslots
int 21h ; then complain
mov ax,4c01h
int 21h ; and exit to DOS
noerr2: mov al,20h
call readint
mov ax,es
cmp ax,bp
jnz err3 ; is int 20h pointing to the resident StopPrg ?
mov al,13h
call readint
mov ax,es
cmp ax,bp
jnz err3 ; is int 13h pointing to the resident StopPrg ?
mov al,27h
call readint
mov ax,es
cmp ax,bp
jnz err3 ; is int 27h pointing to the resident StopPrg ?
mov al,21h
call readint
mov ax,es
cmp ax,bp
jnz err3 ; is Int 21h pointing to the resident StopPrg ?
mov al,9
call readint
mov ax,es
cmp ax,bp
jnz err3 ; is Int 9h pointing to the resident StopPrg ?
mov al,8
call readint
mov ax,es
cmp ax,bp
jz noerr3 ; is Int 8h pointing to the resident StopPrg ?
err3: call progname ; disp. prog name even if asked not to do it
; (before complaining)
mov ah,9
mov dx,offset messerrothers
int 21h
mov ax,4c01h ; if not so, complain and exit to DOS
int 21h
noerr3: mov es,bp
lds dx,es:old8 ; restore Int 8h vector
mov al,8
call setint
lds dx,es:old9 ; restore Int 9h vector
mov al,9
call setint
lds dx,es:old13 ; restore Int 13h vector
mov al,13h
call setint
lds dx,es:old21 ; restore Int 21h vector
mov al,21h
call setint
lds dx,es:old20 ; restore Int 20h vector
mov al,20h
call setint
lds dx,es:old27 ; restore Int 27h vector
mov al,27h
call setint ; (we are accessing the resident StopPrg's
; variables)
push cs
pop ds
mov ah,49h ; free the resident StopPrg's segment
int 21h
cmp nomsg,0
jnz no_msg2
mov ah,9
mov dx,offset messuninstok
int 21h ; if not asked to shut up ...
no_msg2: mov ax,4c00h ; say everything OK and exit to DOS
int 21h
; we were asked to install
nouninst: mov ah,34h
int 21h
mov wo dosavail,bx
mov wo dosavail[2],es ; get InDos Ptr
mov es,wo cs:[2ch] ; free our own environment
mov ah,49h
int 21h
mov ax,3022h ; is StopPrg already installed ?
int 21h
cmp cx,1112h
jnz notyet
jmp already ; if so, jmp to "already"
notyet: push cs
pop ds
mov al,8
call readint ; read int 8 vector
cmp wo es:[bx+1dh],0a1fah
jnz nosdk2
cmp wo es:[bx+1fh],26h
jnz nosdk2
cmp wo es:[bx+25h],74c3h
jnz nosdk2 ; is SideKick hooked on int 8 ?
mov by es:[bx+26h],0ebh
; if so, poke a byte in its code
; (see new8 for explanations)
nosdk2: mov al,13h ; read int 13h vector
call readint
mov wo old13,bx
mov wo old13[2],es
mov al,13h ; put new int 13h vector
mov dx,offset new13
call setint
mov al,21h ; read int 21h vector
call readint
mov wo old21,bx
mov wo old21[2],es
mov al,21h ; put new int 21h vector
mov dx,offset new21
call setint
mov al,9 ; read int 9h vector
call readint
mov wo old9,bx
mov wo old9[2],es
mov al,9 ; put new int 9h vector
mov dx,offset new9
call setint
mov al,8 ; read int 8h vector
call readint
mov wo old8,bx
mov wo old8[2],es
mov al,8 ; put new int 8h vector
mov dx,offset new8
call setint
mov al,20h ; read int 20h vector
call readint
mov wo old20,bx
mov wo old20[2],es
mov al,20h ; put new int 20h vector
mov dx,offset new20
call setint
mov al,27h ; read int 27h vector
call readint
mov wo old27,bx
mov wo old27[2],es
mov al,27h ; put new int 27h vector
mov dx,offset new27
call setint
xor ax,ax
mov ds,ax
push cs
pop es
xor si,si
mov di,offset ints
mov cx,200h
cld
rep movsw ; make a copy of the interrupt table
push cs
pop ds
cmp nomsg,0
jnz noinfo
mov ah,9
mov dx,offset messhotkey
int 21h
noinfo: mov dx,offset install[3]
int 27h ; terminate stay resident
; StopPrg was called when it was already resident
already: call progname ; disp. prog name even if asked not to do it
; (before complaining)
mov ah,9
mov dx,offset messalready
push cs
pop ds
int 21h ; say we were already installed
mov ax,4c01h
int 21h ; exit to DOS
;;;;;;;;;;;;;;;;;;;;;;;;;;;;; PROCEDURES ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
progname proc
push cs
pop ds ; in case DS was wrong
cmp nomsg,0
jz skip_it ; if nomsg is 0, then it was already printed
mov ah,9
mov dx,offset messprg
int 21h ; display prog name and info
mov nomsg,0 ; so that it will not print it again if
; called twice
skip_it: ret
progname endp
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; MESSAGES ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
messprg db 0dh,0ah,' ───────────────────────────────────────────'
db 0dh,0ah,' StopPrg v2.0 (c) by MAK-TRAXON''s Prophet'
db 0dh,0ah,' Exit to DOS from any program !'
db 0dh,0ah,' ───────────────────────────────────────────'
db 0dh,0ah,' Syntax: StopPrg [/U] [/N] [/M]'
db 0dh,0ah,' U: UnInstall N: No messages'
db 0dh,0ah,' M: Maximum compatibility with other TSR''s'
db 0dh,0ah,' ───────────────────────────────────────────'
db 0dh,0ah,'$'
messerrnoinst db ' You can''t UnInstall when it is not even'
db 0dh,0ah,' INSTALLED !!!'
db 0dh,0ah,' ───────────────────────────────────────────'
db 0dh,0ah,'$'
messerrothers db ' You must first remove other TSR''s'
db 0dh,0ah,' ───────────────────────────────────────────'
db 0dh,0ah,'$'
messuninstok db ' StopPrg was correctly uninstalled'
db 0dh,0ah,' ───────────────────────────────────────────'
db 0dh,0ah,'$'
messalready db ' StopPrg was already installed !'
db 0dh,0ah,' ───────────────────────────────────────────'
db 0dh,0ah,'$'
messhotkey db ' Hot Key: Alt - Ctrl - ',11h,'─┘'
db 0dh,0ah,' ───────────────────────────────────────────'
db 0dh,0ah,'$'
messwrongcmd db ' Unrecognized command line option !'
db 0dh,0ah,' ───────────────────────────────────────────'
db 0dh,0ah,'$'
messerrslots db ' Impossible to UnInstall: StopPrg had to'
db 0dh,0ah,' take Int 9 back from some other program'
db 0dh,0ah,' ───────────────────────────────────────────'
db 0dh,0ah,'$'
progseg ends
end entpt